package br.com.jhd.aba.mapeadordados.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.log4j.Logger;

import br.com.jhd.aba.dominio.repositorios.IRepository;

public abstract class GenericDAOWithJPA<T, ID extends Serializable> implements IRepository<T,ID> {

		private static final Logger LOG = Logger.getLogger(GenericDAOWithJPA.class);

		private Class<T> classePersistente;

		@PersistenceContext
	 	protected EntityManager entityManager;
		
		

	 	@SuppressWarnings("unchecked")
	    public GenericDAOWithJPA() {
	        this.classePersistente = (Class<T>) ((ParameterizedType) getClass()
	                                .getGenericSuperclass()).getActualTypeArguments()[0];
	    }

	    public Class<T> classeDoObjeto() {
	    	LOG.info("Retornando a classe da entidade");
	        return classePersistente;
	    }

	    public void adicionar(T entity) {
	    	LOG.info("Adicionando objeto do tipo " + classePersistente.toString());
	        entityManager.persist(entity);
	    }

	    public void atualizar(T entity) {
	    	LOG.info("Atualizando objeto do tipo " + classePersistente.toString());
	        entityManager.merge(entity);
	    }

	    public void remover(T entity) {
	    	LOG.info("Apagando objeto do tipo " + classePersistente.toString());
	        entityManager.remove(entity);
	    }

	    public void recarregar(T entity) {
	    	LOG.info("Recarregando objeto do tipo " + classePersistente.toString());
	        entityManager.refresh(entity);
	    }

	    public T encontrarPorId(ID id) {
	    	LOG.info("Retornando objeto do tipo " + classePersistente.toString() + " pelo Id " + id.toString());
	    	return entityManager.find(classePersistente, id);
		}

	    @SuppressWarnings("unchecked")
	    public List<T> carregarTodos() {
	    	LOG.info("Carregando todos objetos do tipo " + classePersistente.toString());
	        return entityManager.createQuery("Select t from " + classePersistente.getSimpleName() + " t")
	        						.getResultList();
	    }

	    @SuppressWarnings("unchecked")
		public List<T> carregarTodosComIntervalo(final int inicio, final int fim) {
	    	LOG.info("Carregando todos objetos do tipo " + classePersistente.toString() + " com intervalo");
			return entityManager.createQuery("Select t from " + classePersistente.getSimpleName() + " t")
									.getResultList().subList(inicio, fim);
		}

	    @SuppressWarnings("unchecked")
	    public List<T> encontrarComQuery(String query) {
	    	LOG.info("Carregando objetos do tipo " + classePersistente.toString() + " com query");
	    	return entityManager.createQuery(query).getResultList();
	    }

	    @SuppressWarnings("unchecked")
	    public List<T> encontrarComQueryEIntervalo(String query, final int inicio, final int fim) {
	    	LOG.info("Carregando objetos do tipo " + classePersistente.toString() + " com query e intervalo");
	    	return entityManager.createQuery(query).getResultList().subList(inicio, fim);
	    }

}
